package main

import (
	"net/http"
)

const doc = `
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8" />
	<title>Bouncer service</title>
	<!--[if IE]>
		<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
	<![endif]-->
</head>
<body>
 <h1>Bouncer service</h1>

  <p>Bouncer is an HTTP-based rendezvous protocol. It enables two
    clients to talk to each other, using this server as an
    intermediary. It essentially allows two clients who expect to be
    communicating to find each other, despite NATs and other
    obstacles.</p>

 <h2>Is this a proxy?</h2>

  <p>No, it's not a proxy. Well, it is a proxy, but probably not the
    kind of proxy you're thinking of. A bouncer server bridges two
    clients that speak and understand the bouncer protocol. It does
    not connect a client to a server, and only works if both clients
    speak the bouncer protocol.</p>

  <p>In other words, a bouncer server is a building block for
    developers who want to get two custom programs talking to each
    other, not a service for end users, or even browsers.</p>

 <h2>How does it work?</h2>

  <p>Simple. You, an HTTP client, make a request that looks like
    this:</p>

<pre>GET /bounce/some_key HTTP/1.1
Host: {{.Host}}
Upgrade: TCP
</pre>

  <p>This request will hang on the server until it gets another
    request for the same path key. When it does, it responds to both
    requests by switching protocols:</p>

<pre>HTTP/1.1 101 Switching Protocols
Upgrade: TCP
Content-Length: 0
X-Bouncer-Order: first
</pre>

  <p>After the response headers are transmitted, each client can use
    the (formerly) HTTP connection as a raw TCP connection to the
    other client, and continue with whatever protocol they fancy.</p>

  <p>To aid clients who want to speak a client/server protocol, the
    bouncer server includes the <tt>X-Bouncer-Order</tt> header in
    its response to both clients. One client receives the value
    "first", the other "second". Clients may choose to use this as a
    role hint, but are under no obligation to.</p>

 <h2>What bounce keys can I use?</h2>

  <p>Any URL-valid string rooted under <tt>/bounce/</tt>. All the
    following are valid bounce URLs:</p>

<pre>/bounce/hello
/bounce/my-app/client-15
/bounce/1/2/3/4/5/6/7/
/bounce/28732529875332547357235847298375329
</pre>

  <p>This also implies that there is no namespacing. If you can use a
    bounce URL, so can anyone else. This brings us to...</p>

 <h2>How secure is a bounced connection?</h2>

  <p>No more secure than a plain, unencrypted TCP connection. That is,
    not at all. Worse, you <em>know</em> that there is a
    man-in-the-middle, since you explicitly brought it into the
    equation.</p>

  <p>This means that if you expect to be talking to someone in
    particular, immediately after getting switched by the bouncer you
    should authenticate your peer, and use a protocol with strong
    integrity checking to prevent any en-route tampering. If you don't
    want the world (and the bouncer server in particular) to see what
    you're saying, you should also encrypt your traffic.</p>

  <p>The easiest way to accomplish this is to set up a TLS session
    immediately after getting switched, and require both ends to
    present a certificate the other recognizes. There are of course
    other protocols you can use (e.g. SSH), it's all bits and bytes to
    the bouncer server.</p>

  <p>Another thing to consider is that if you make the initial HTTP
    request over plain TCP, anyone can see the bounce URL you're
    requesting. This means that even if you bounce using
    <tt>/bounce/&lt;1KiB random string here&gt;</tt>, that is
    <em>not</em> a guarantee that only the peers you expect will
    connect to you. If you need that guarantee, wait until the
    connection is established and run a secure authentication
    protocol.</p>

 <h2>What does the server log?</h2>

  <p>While I can't speak for all servers that might choose to
    implement this protocol, the server serving this page, if it
    hasn't been modified, will log only metadata about your
    sessions. Stuff like your IP, the IP of the peer you got connected
    to, when the session started/ended, the amount of data sent...</p>

  <p>In particular, the server at this time does not log any of the
    bytes the clients send after the protocol switch has occured. But
    again, why should you trust a random person on the internet? I
    recommend you use a protocol that includes strong privacy and
    integrity, to prevent both eavesdropping and tampering on the
    server.</p>

 <h2>What can a bouncer be used for?</h2>

  <p>Many things, in all likelihood. I developed bouncer with a couple
    of ideas in mind:</p>

  <ul>

    <li>A dead simple, low bandwidth side-channel for clients to
      echange <a
      href="http://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment">ICE</a>
      information, to establish a direct p2p connection (possibly
      punching through NATs and such).

    <li>As a backend for a trivial <a href="http://xkcd.com/949/">file
      transfer</a> site, which pushes A's POST body directly into B's
      GET response. The full protocol may not be necessary for this
      application, but the implementation can definitely be
      repurposed.

    <li>Some kind of crazy hippie swarm, where thousands of clients
      connect to the same bouncer URL, get matched up at random, and
      do something cool together, connect again to form a new pair,
      and so forth.

    <li>An ssh ProxyClient, and a tiny daemon that publishes all my
      sshds (especially those behind NAT) on semi-private (see above)
      URLs. e.g., <tt>/dave/ssh/&lt;server name&gt;</tt> connects you
      to the sshd on that machine. Possibly increased risk of
      bruteforce, possibly awesome. Haven't decided.

  </ul>

 <h2>Where's the source code?</h2>

  <p>In a <a href="http://bouncer.googlecode.com/">Google Code
    project</a>. The project contains this server, a client library
    for the <a href="http://golang.org">Go programming language</a>,
    and some utilities for implementing concurrent client rendezvous
    in Go.</p>

</body>
</html>
`

func documentation(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		w.WriteHeader(404)
		return
	}
	w.Write([]byte(doc))
}
